/*
 * Copyright 2019 xiaomaoguai.com All right reserved. This software is the
 * confidential and proprietary information of xiaomaoguai.com ("Confidential
 * Information"). You shall not disclose such Confidential Information and shall
 * use it only in accordance with the terms of the license agreement you entered
 * into with xiaomaoguai.com.
 */

package com.xiaomaoguai.tac.cloud.apm.logging.logback;

import ch.qos.logback.classic.LoggerContext;
import ch.qos.logback.classic.PatternLayout;
import ch.qos.logback.classic.pattern.EnsureExceptionHandling;
import ch.qos.logback.classic.pattern.ExtendedThrowableProxyConverter;
import ch.qos.logback.classic.spi.ILoggingEvent;
import ch.qos.logback.core.Context;
import ch.qos.logback.core.pattern.Converter;
import ch.qos.logback.core.pattern.ConverterUtil;
import ch.qos.logback.core.pattern.PatternLayoutEncoderBase;

/**
 * 用于支持输出异常堆栈的时候，也能正常过滤敏感信息
 *
 * @author chenyao
 * @see ch.qos.logback.classic.encoder.PatternLayoutEncoder
 * @since 2019年5月15日 上午10:25:14
 */
public class SensitiveDataPatternLayoutEncoder extends PatternLayoutEncoderBase<ILoggingEvent> {

	@Override
	public void start() {
		PatternLayout patternLayout = new PatternLayout();
		patternLayout.setContext(context);
		patternLayout.setPattern(getPattern());
		patternLayout.setOutputPatternAsHeader(outputPatternAsHeader);
		patternLayout.setPostCompileProcessor(new EnsureExceptionHandling() {

			@Override
			public void process(Context context, Converter<ILoggingEvent> head) {
				if (head == null) {
					// this should never happen
					throw new IllegalArgumentException("cannot process empty chain");
				}
				if (!chainHandlesThrowable(head)) {
					Converter<ILoggingEvent> tail = ConverterUtil.findTail(head);
					Converter<ILoggingEvent> exConverter = null;
					LoggerContext loggerContext = (LoggerContext) context;
					if (loggerContext.isPackagingDataEnabled()) {
						exConverter = new ExtendedThrowableProxyConverter();
					} else {
						exConverter = new SensitiveDataThrowableProxyConverter();
					}
					tail.setNext(exConverter);
				}
			}
		});
		patternLayout.start();
		this.layout = patternLayout;
		super.start();
	}

}
